package cn.bonoon.kernel.descriptors.impl;

import java.lang.reflect.Field;

import org.springframework.util.ClassUtils;

import cn.bonoon.kernel.IOptionArray;
import cn.bonoon.kernel.annotations.OptionArray;
import cn.bonoon.kernel.annotations.OptionExclude;
import cn.bonoon.kernel.annotations.ResetProperty;
import cn.bonoon.kernel.descriptors.ClassPropertyAccessor;

abstract class MappablePropertyAccessor<T extends ClassPropertyAccessor, C extends MappableClassDescriptor<T>> extends AbstractPropertyAccessor{
	protected final C classDescriptor;
	
	protected MappablePropertyAccessor(C classDescriptor, Field field) {
		super(classDescriptor.clazz, field);
		this.classDescriptor = classDescriptor;
	}

	public ResetProperty getPropertyReseter() {
		return classDescriptor.getPropertyReseter(getName());
	}
	
	public boolean isNumber() {
		return ClassUtils.isAssignable(Number.class, type);
	}
	
	public boolean isBoolean() {
		return boolean.class.equals(type) || Boolean.class.equals(type);
	}

	public IOptionArray getOptionArray() {
		OptionArray oa = field.getAnnotation(OptionArray.class);
		if(null == oa || oa.value().length == 0){
			ResetProperty rp = classDescriptor.getPropertyReseter(getName());
			if(rp != null && rp.options().value().length > 0){
				oa = rp.options();
			}else{
				return null;
			}
		}
		OptionExclude oe = field.getAnnotation(OptionExclude.class);
		return new OptionArrayImpl(oa, oe);
	}

	private class OptionArrayImpl implements IOptionArray{
		final OptionArray oa;
		final int length;
		int[] excludes;
		int start, end;
		String replace = "";
		
		OptionArrayImpl(OptionArray oa, OptionExclude oe){
			this.oa = oa;
			this.length = oa.value().length;
			
			if(null != oe){
				excludes = oe.value();
				start = oe.start();
				end = oe.end();
				replace = oe.replace();
			}
			
			if(start >= length || start < 0){
				start = 0;
			}
			
			if(end > length || end <= 0){
				end = length;
			}
		}
		
		@Override
		public String[] mergeArray() {
			if(null != excludes){
				String[] oavs = oa.value();
				
				for(int exclude : excludes){
					if(exclude >= 0 && exclude < length){
						oavs[exclude] = replace;
					}
				}
				
				for(int i = 0; i < start; i++){//定义了开始
					oavs[i] = replace;
				}
				
				for(int i = end; i < length; i++){//定义了结束
					oavs[i] = replace;
				}
			}
			return oa.value();
		}
		
		@Override
		public int offset() {
			return oa.offset();
		}

		@Override
		public String[] array() {
			return oa.value();
		}

		@Override
		public String overflow() {
			return oa.overflow();
		}

		@Override
		public int[] excludes() {
			return excludes;
		}

		@Override
		public int start() {
			return start;
		}

		@Override
		public int end() {
			return end;
		}

		@Override
		public String replace() {
			return replace;
		}
		
	}
	
	public boolean is(Class<?> type) {
		return type.equals(this.type);
	}
	
	public boolean is(Class<?>... types) {
		for(Class<?> type : types){
			if(type.equals(this.type)){
				return true;
			}
		}
		return false;
	}
}
